package com.zl.smartmall.library.account;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.http.Header;
import org.apache.http.client.CookieStore;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.json.JSONException;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;

import com.loopj.android.http.RequestParams;
import com.zl.smartmall.library.account.po.CookieInfo;
import com.zl.smartmall.library.account.po.UserInfo;
import com.zl.smartmall.library.account.vo.CookieInfoDao;
import com.zl.smartmall.library.account.vo.UserInfoDao;
import com.zl.smartmall.library.concurrent.ThreadExecutor;
import com.zl.smartmall.library.listener.LogoutListener;
import com.zl.smartmall.library.listener.RegisterCidListener;
import com.zl.smartmall.library.listener.RegisterTagListener;
import com.zl.smartmall.library.listener.UserInfoListener;
import com.zl.smartmall.library.listener.WechatAccessTokenListener;
import com.zl.smartmall.library.listener.WechatUserinfoListener;
import com.zl.smartmall.library.util.Constants;
import com.zl.smartmall.library.util.CrashHandler;
import com.zl.smartmall.library.util.PreferenceModel;
import com.zl.smartmall.library.util.SingtonAsyncHttpClient;
import com.zl.smartmall.library.util.Tools;

/**
 * 账户管理相关操作接口<p>
 * 具有账户登录、注销等一些和账户相关的操作接口
 * @author 陈希然
 *
 */
public class IAuth {

	private static final String TAG = IAuth.class.getSimpleName();
	private static final int MSG_SAVE_USERINFO_FINISH = 1;
	private static final int MSG_LOAD_USERINFO_FINISH = 2;
	
	private static IAuth mInstance;
	private static Lock mLock;
	private Context mContext;
	private CookieStore mCookieStore;
	private Handler mHandler;
	private UserInfo mUserInfo;

	static{
		mLock = new ReentrantLock();
	}
	
	private IAuth(Context context) {
		mContext = context;
		mHandler = new IAuthHandler(Looper.myLooper());
		loadCookieStoreAsyn();
		loadUserInfoAsyn();
	}
	
	public static IAuth getInstance() {
		return mInstance;
	}
	
	public static void init(Context context) {
		if(mInstance == null){
//        	mLock = new ReentrantLock();
    		mLock.lock();
//    		synchronized (mLock) {
    		try{
				if(mInstance == null){
					mInstance = new IAuth(context);
				}
    		}finally{
    			mLock.unlock();
    		}
//			}
    	}
	}
	
	
	/**
	 * 清除本地用户信息及Cookie
	 */
	public void clearUserInfo() {
		mUserInfo = null;
		ThreadExecutor.getInstance().execute(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				CookieInfoDao cookieInfoDao = new CookieInfoDao(mContext);
				cookieInfoDao.delete();
				mCookieStore = null;
				PreferenceModel.remove(Constants.PREFERENCE_KEY_COMMUNITY_ID);;
				PreferenceModel.remove(Constants.PREFERENCE_KEY_COMMUNITY_NAME);;
				PreferenceModel.remove(Constants.PREFERENCE_KEY_HAS_COMMUNITY);;
				PreferenceModel.remove(Constants.PREFERENCE_KEY_UID);
//				PreferenceModel.putString(Constants.PREFERENCE_KEY_TOKEN, userInfo.getToken());
				PreferenceModel.remove(Constants.PREFERENCE_KEY_LOGIN_PLATFORM);
				UserInfoDao userInfoDao = new UserInfoDao(mContext);
				userInfoDao.delete();
			}
		});
	}
	
	private void loadCookieStoreAsyn() {
		ThreadExecutor.getInstance().execute(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				mCookieStore = loadCookieStoreSync();
			}
		});
	}
	
	/**
	 * 是否有效用户
	 * @return 返回true表示该用户为有效用户
	 */
	public boolean isUserValid() {
		return loadCookieStore() != null && loadUserInfo() != null;
	}
	
	private CookieStore loadCookieStoreSync() {
		CookieInfoDao cookieInfoDao = new CookieInfoDao(mContext);
		CookieInfo cookieInfo = cookieInfoDao.query();
		if(cookieInfo != null) {
			String cookieName = "Set-Cookie";
			String cookieValue = cookieInfo.getCookieValue();
			if (!TextUtils.isEmpty(cookieValue)) {
				CookieStore mCookieStore = new BasicCookieStore();
				BasicClientCookie cookie = new BasicClientCookie(cookieName, cookieValue);
				cookie.setVersion(0);
				cookie.setDomain("");
				cookie.setPath("/");
				mCookieStore.addCookie(cookie);
				
				CrashHandler.d(TAG, "cookie值 = " + cookieValue);
				
				return mCookieStore;
			}
		}
		return null;
	}
	
	/**
	 * 获取用户信息cookie
	 * @return 用户信息cookie
	 */
	public CookieStore loadCookieStore() {
		if(mCookieStore == null) {
			mCookieStore = loadCookieStoreSync();
		}
		return mCookieStore;
	}

	/**
	 * 登录至后台服务器
	 * @param loginPlatform 第三方登录平台; 取值为{@link LoginPlatform#QQ}、{@link LoginPlatform#WECHAT}
	 * @param accessToken 第三方登录accessToken
	 * @param openId 第三方登录openId
	 * @param nickname 第三方登录昵称
	 * @param face 第三方登录头像
	 * @param gender 第三方登录性别
	 * @param userInfoListener 回调监听器
	 */
	public void login(final LoginPlatform loginPlatform, String accessToken, 
			String openId, String nickname, String face, String gender, final UserInfoListener userInfoListener) {
		if(!Tools.hasInternetConnection(mContext)) {
			userInfoListener.onNoNetWork();
			return;
		}
		RequestParams params = new RequestParams();
		params.put("t", loginPlatform.getValue());//第三方类型：qq QQ登录，tencentweibo 腾讯微博，sinaweibo 新浪微博，weixin 微信登录
		params.put("mac", Tools.getLocalMacAddress(mContext));
		params.put("imei", Tools.getIMEI(mContext));
		params.put("access_token", accessToken);
		params.put("alias", Tools.md5(Tools.getLocalMacAddress(mContext) + Tools.getIMEI(mContext)));//推送的别名，是设备 mac和imei的md5字符串
		params.put("openid", openId);
		params.put("nickname", nickname);
		params.put("gender", gender);
		params.put("head", face);
		
		SingtonAsyncHttpClient.getInstance().post(Constants.URL_LOGIN, params, new UserInfoListener() {
			
			@Override
			public void onResponseFailed() {
				// TODO Auto-generated method stub
				userInfoListener.onResponseFailed();
			}
			
			@Override
			public void onResponseSuccess(Header[] headers, UserInfo userInfo) {
				// TODO Auto-generated method stub
				if(userInfo != null) {
					userInfo.setLoginPlatform(loginPlatform.getValue());
					CookieInfo cookieInfo = CookieInfo.parse(headers, userInfo.getUid(), userInfo.getLoginType());
					String cookieName = "Set-Cookie";
					String cookieValue = cookieInfo.getCookieValue();
					if (!TextUtils.isEmpty(cookieValue)) {
						mCookieStore = new BasicCookieStore();
						BasicClientCookie cookie = new BasicClientCookie(cookieName, cookieValue);
						cookie.setVersion(0);
						cookie.setDomain("");
						cookie.setPath("/");
						mCookieStore.addCookie(cookie);
					}
					saveUserInfo(cookieInfo, userInfo, userInfoListener);
				
				}else {
					onResponseFailed();
				}
			}
			
			@Override
			public void onResponseSuccess(UserInfo userInfo) {
				// TODO Auto-generated method stub
				
//				if(userInfo != null) {
//					userInfo.setLoginPlatform(loginPlatform.name());
//					saveUserInfo(context, userInfo, listener);
//				
//				}else {
//					onResponseFailed();
//				}

			}

			@Override
			public void onNoNetWork() {
				// TODO Auto-generated method stub
				userInfoListener.onNoNetWork();
			}
		});
		
	}
	
	/**
	 * 注销账户
	 * @param logoutListener 回调监听器
	 */
	public void logout(LogoutListener logoutListener) {
		if(!Tools.hasInternetConnection(mContext)) {
			logoutListener.onNoNetWork();
		
		}else {
			RequestParams params = new RequestParams();
			params.put("version", Tools.getAppVersionName(mContext));
			SingtonAsyncHttpClient.getInstance().get(Constants.URL_LOGOUT, params, logoutListener);
			CrashHandler.d(TAG, "url = " + Constants.URL_LOGOUT + "?" + params);
		}
	}
	
	private void loadUserInfoAsyn() {
		ThreadExecutor.getInstance().execute(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				mUserInfo = loadUserInfoSync();
			}
			
		});
	}
	
	private UserInfo loadUserInfoSync() {
		int uid = PreferenceModel.getInt(Constants.PREFERENCE_KEY_UID, -1);
		if(uid != -1) {
			UserInfoDao dao = new UserInfoDao(mContext);
			return dao.query(uid);
		}
		return null;
	}
	
	/**
	 * 获取用户信息cookie
	 * @return 用户信息cookie
	 */
	public UserInfo loadUserInfo() {
		if(mUserInfo == null) {
			mUserInfo = loadUserInfoSync();
		}
		return mUserInfo;
	}
	
	/**
	 * 加载本地用户信息
	 * @param context ApplicationContext
	 * @param listener 回调监听器
	 */
//	public void loadUserInfo(final Context context, final UserInfoListener listener) {
//		ThreadExecutor.getInstance().execute(new Runnable() {
//			
//			@Override
//			public void run() {
//				// TODO Auto-generated method stub
//				UserInfo userInfo = null;
//				int uid = PreferenceModel.getInt(Constants.PREFERENCE_KEY_UID, -1);
//				if(uid != -1) {
//					UserInfoDao dao = new UserInfoDao(context);
//					userInfo = dao.query(uid);
//				}
//				
//				MessageData msgData = new MessageData();
//				msgData.listener = listener;
//				msgData.userInfo = userInfo;
//				Message msg = Message.obtain(mHandler, MSG_LOAD_USERINFO_FINISH, msgData);
//				mHandler.sendMessage(msg);
//			}
//		});
//	}
	
	/**
	 * 保存用户信息及Cookie
	 * @param cookieInfo
	 * @param userInfo
	 * @param listener 回调监听器
	 */
	private void saveUserInfo(final CookieInfo cookieInfo, final UserInfo userInfo, final UserInfoListener listener) {
		ThreadExecutor.getInstance().execute(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				try {
					//存储cookie
					if(cookieInfo != null) {
						CookieInfoDao cookieInfoDao = new CookieInfoDao(mContext);
						cookieInfoDao.delete();
						cookieInfoDao.insert(cookieInfo);
					}
					
					PreferenceModel.putInt(Constants.PREFERENCE_KEY_UID, userInfo.getUid());
//					PreferenceModel.putString(Constants.PREFERENCE_KEY_TOKEN, userInfo.getToken());
					PreferenceModel.putString(Constants.PREFERENCE_KEY_LOGIN_PLATFORM, userInfo.getLoginPlatform());
					UserInfoDao userInfoDao = new UserInfoDao(mContext);
					userInfoDao.delete();
					userInfoDao.insert(userInfo);
					
					MessageData msgData = new MessageData();
					msgData.listener = listener;
					msgData.userInfo = userInfo;
					Message msg = Message.obtain(mHandler, MSG_SAVE_USERINFO_FINISH, msgData);
					mHandler.sendMessage(msg);
					
				} catch (JSONException e) {
					CrashHandler.e(e);
				}
			}
		});
	}
	
	/**
	 * 注册推送cid
	 * @param cid 推送发个推送过来的cid
	 * @param registerCidListener 回调监听器
	 */
	public void registerCID(String cid, RegisterCidListener registerCidListener) {
		if(!Tools.hasInternetConnection(mContext)) {
			registerCidListener.onNoNetWork();
			return;
		}
		RequestParams params = new RequestParams();
		params.put("clientid", cid);
		params.put("uid", loadUserInfo().getUid());
//		url = String.format(url+"?clientid=%s&uid=%s", cid, loadUserInfo().getUid()+"");
		SingtonAsyncHttpClient.getInstance().setCookieStore(mCookieStore);
		SingtonAsyncHttpClient.getInstance().get(Constants.URL_REGISTER_CID, params, registerCidListener);
		CrashHandler.d(TAG, "url = " + Constants.URL_REGISTER_CID + "?" + params);
	}
	
	/**
	 * 注册推送tag
	 * @param tag 过滤的tag
	 * @param registerTagListener 回调监听器
	 */
	public void registerTAG(String tag, RegisterTagListener registerTagListener) {
		if(!Tools.hasInternetConnection(mContext)) {
			registerTagListener.onNoNetWork();
			return;
		}
		RequestParams params = new RequestParams();
		params.put("tags", tag);
		params.put("uid", loadUserInfo().getUid());
		SingtonAsyncHttpClient.getInstance().setCookieStore(mCookieStore);
		SingtonAsyncHttpClient.getInstance().get(Constants.URL_REGISTER_TAG, params, registerTagListener);
		CrashHandler.d(TAG, "url = " + Constants.URL_REGISTER_TAG + "?" + params);
	}
	
	/**
	 * 从微信服务器获取微信AccessToken
	 * @param code 用户换取access_token的code
	 * @param appId 应用唯一标识，在微信开放平台提交应用审核通过后获得
	 * @param appSecret 应用密钥AppSecret，在微信开放平台提交应用审核通过后获得
	 * @param wechatAccessTokenListener 回调监听器
	 */
	public void getWeChatAccessToken(String code, String appId, String appSecret, WechatAccessTokenListener wechatAccessTokenListener) {
		if(!Tools.hasInternetConnection(mContext)) {
			wechatAccessTokenListener.onNoNetWork();
			return;
		}
		RequestParams params = new RequestParams();
		params.put("appid", appId);
		params.put("secret", appSecret);
		params.put("code", code);
		params.put("grant_type", "authorization_code");
		SingtonAsyncHttpClient.getInstance().get(Constants.URL_WECHAT_ACCESS_TOKEN, params, wechatAccessTokenListener);
		CrashHandler.d(TAG, "url = " + Constants.URL_WECHAT_ACCESS_TOKEN + "?" + params);
	}
	
	/**
	 * 从微信服务器获取用户资料
	 * @param accessToken 微信接口调用凭证
	 * @param openId 微信授权用户唯一标识
	 * @param wechatUserinfoListener 回调监听器
	 */
	public void getWeChatUserInfo(String accessToken, String openId, WechatUserinfoListener wechatUserinfoListener) {
		if(!Tools.hasInternetConnection(mContext)) {
			wechatUserinfoListener.onNoNetWork();
			return;
		}
		RequestParams params = new RequestParams();
		params.put("access_token", accessToken);
		params.put("openid", openId);
		SingtonAsyncHttpClient.getInstance().get(Constants.URL_WECHAT_USER_INFO, params, wechatUserinfoListener);
		CrashHandler.d(TAG, "url = " + Constants.URL_WECHAT_USER_INFO + "?" + params);
	}
	
	
	/**
     * Avoid leaks by using a non-anonymous handler class.
     */
	private static class IAuthHandler extends Handler {
		
		public IAuthHandler(Looper looper) {
			super(looper);
		}
		
		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			MessageData msgData;
			switch (msg.what) {
			case MSG_SAVE_USERINFO_FINISH:
				CrashHandler.d(TAG, "缓存账户信息成功");
				msgData = (MessageData) msg.obj;
				msgData.listener.onResponseSuccess(msgData.userInfo);
				break;

			case MSG_LOAD_USERINFO_FINISH:
				CrashHandler.d(TAG, "加载账户信息成功");
				msgData = (MessageData) msg.obj;
				msgData.listener.onResponseSuccess(msgData.userInfo);
				break;
				
			default:
				break;
			}
		}
	}
	
	private static class MessageData { 
		UserInfoListener listener;
		UserInfo userInfo;
	}
}
